
#include "usb_com.h"
#include "string.h"
#include "usbd_customhid.h"
#include "usb_device.h"
#include "func_uart.h"
#include "func_adc.h"
#include "func_iic_master.h"
#include "func_iic_slave.h"
#include "func_spi_master.h"
#include "func_spi_slave.h"
#include "func_update.h"
#include "func_gpio.h"
#include "func_pwm.h"

// 发送命令
const SendCmd sendCmd[] =
{
    {COMM_UART, COMM_SUB_UART_SET_PARAM, usb_reply_ok},
    {COMM_UART, COMM_SUB_UART_SEND, usb_reply_ok},
    {COMM_UART, COMM_SUB_UART_REC, uart_rec_update},

    {COMM_ADC, COMM_SUB_ADC_UPDATE, adc_send_data},

    {COMM_IIC_MASTER, COMM_SUB_IIC_MASTER_SET_PARAM, usb_reply_ok},
    {COMM_IIC_MASTER, COMM_SUB_IIC_MASTER_WRITE, usb_reply_ok},
    {COMM_IIC_MASTER, COMM_SUB_IIC_MASTER_READ, iic_master_read_update},

    {COMM_IIC_SLAVE, COMM_SUB_IIC_SLAVE_SET_PARAM, usb_reply_ok},
    {COMM_IIC_SLAVE, COMM_SUB_IIC_SLAVE_WRITE, usb_reply_ok},
    {COMM_IIC_SLAVE, COMM_SUB_IIC_SLAVE_READ, iic_slave_read_update},

    {COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_SET_PARAM, usb_reply_ok},
    {COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE, usb_reply_ok},
    {COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_READ, spi_master_rec_update},
    {COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE_READ, spi_master_send_rec_update},

    {COMM_SPI_SLAVE, COMM_SUB_SPI_SLAVE_SET_PARAM, usb_reply_ok},
    {COMM_SPI_SLAVE, COMM_SUB_SPI_SLAVE_WRITE, usb_reply_ok},
    {COMM_SPI_SLAVE, COMM_SUB_SPI_SLAVE_READ, spi_slave_rec_update},


    {COMM_GPIO, COMM_SUB_GPIO_PIN_SET, usb_reply_ok},
    {COMM_GPIO, COMM_SUB_GPIO_HL_CHANGE, usb_reply_ok},
    {COMM_GPIO, COMM_SUB_GPIO_LEVEL_SET, usb_reply_ok},
    {COMM_GPIO, COMM_SUB_GPIO_LEVEL_READ, gpio_read_level_update},

    {COMM_PWM, COMM_SUB_PWM_SET_PARAM, usb_reply_ok},
    {COMM_PWM, COMM_SUB_PWM_OPEN_CLOSE, usb_reply_ok},

    {COMM_UPDATE, COMM_SUB_UPDATE_BEGIN, update_start_update},
    {COMM_UPDATE, COMM_SUB_UPDATE_VERSION, update_version_update},
};


// 接收命令
const RecCmd recCmd[] =
{
    {COMM_UART, COMM_SUB_UART_SET_PARAM, uart_set_param},
    {COMM_UART, COMM_SUB_UART_SEND, uart_send_data},

    {COMM_IIC_MASTER, COMM_SUB_IIC_MASTER_SET_PARAM, iic_master_set_param},
    {COMM_IIC_MASTER, COMM_SUB_IIC_MASTER_WRITE, iic_master_write_data},
    {COMM_IIC_MASTER, COMM_SUB_IIC_MASTER_READ, iic_master_read_data},

    {COMM_IIC_SLAVE, COMM_SUB_IIC_SLAVE_SET_PARAM, iic_slave_set_param},
    {COMM_IIC_SLAVE, COMM_SUB_IIC_SLAVE_WRITE, iic_slave_write_data},
    {COMM_IIC_SLAVE, COMM_SUB_IIC_SLAVE_READ, iic_slave_read_data},

    {COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_SET_PARAM, spi_master_set_param},
    {COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE, spi_master_send_data},
    {COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_READ, spi_master_read_data},
    {COMM_SPI_MASTER, COMM_SUB_SPI_MASTER_WRITE_READ, spi_master_send_read_data},

    {COMM_SPI_SLAVE, COMM_SUB_SPI_SLAVE_SET_PARAM, spi_slave_set_param},
    {COMM_SPI_SLAVE, COMM_SUB_SPI_SLAVE_WRITE, spi_slave_send_data},
    {COMM_SPI_SLAVE, COMM_SUB_SPI_SLAVE_READ, spi_slave_read_data},

    {COMM_GPIO, COMM_SUB_GPIO_PIN_SET, gpio_mode_set},
    {COMM_GPIO, COMM_SUB_GPIO_HL_CHANGE, gpio_more_hl},
    {COMM_GPIO, COMM_SUB_GPIO_LEVEL_SET, gpio_set_level},
    {COMM_GPIO, COMM_SUB_GPIO_LEVEL_READ, gpio_read_level},

    {COMM_PWM, COMM_SUB_PWM_SET_PARAM, pwm_set_param},
    {COMM_PWM, COMM_SUB_PWM_OPEN_CLOSE, pwm_open_close},

    {COMM_UPDATE, COMM_SUB_UPDATE_BEGIN, update_start},
    {COMM_UPDATE, COMM_SUB_UPDATE_VERSION, update_version},
};

uint8_t report[CUSTOM_HID_EPOUT_SIZE];
struct
{
    UsbCmd cmdsQueue[CMD_QUEUE_NUM];
    unsigned char front;        //前指针,指向队首
    unsigned char rear;     //后指针,指向对尾
} CmdQueue;


/// @brief 校验和
/// @param b 校验数组
/// @param len 校验长度
/// @return
unsigned char chksum(unsigned char *b, int len)
{
    unsigned char sum = 0;
    for (int i = 0; i < len; i++)
    {
        sum += b[i];
    }
    return sum;
}


/// @brief usb数据发送
/// @param arr 发送数组
/// @param len 发送长度
void usb_send(unsigned char *arr, unsigned short len)
{
    memset(report, 0, CUSTOM_HID_EPOUT_SIZE);
    memcpy(report, arr, len);
    USB_Send(report, CUSTOM_HID_EPOUT_SIZE);
}


/// @brief 串口接收
/// @param message
/// @param len
void usb_rec(unsigned char *message, unsigned short len)
{
    if (len < 6)
    {
        return;
    }
    else
    {
        if (!((message[0] == 0xaa && message[1] == 0x55) || (message[0] == 0x55 && message[1] == 0xaa)) || message[2] > len) //data len error or header error
        {
            return;
        }
        if (message[message[2] - 1] != chksum(message, message[2] - 1)) // checksum error
        {
            return;
        }

        for (int i = 0; i < sizeof(recCmd) / sizeof(RecCmd); i++) // 查找对应的命令
        {
            if (message[3] == recCmd[i].cmd && message[4] == recCmd[i].subCmd)
            {
                if (recCmd[i].recDeal)
                {
                    recCmd[i].recDeal(recCmd[i].cmd, recCmd[i].subCmd, message);
                }
                break;
            }
        }
    }
}


/// @brief 接收回复
/// @param ok
void usb_reply_ok(unsigned char cmd, unsigned char subCmd, void *ok)
{
    unsigned char reply[7];
    reply[0] = 0xaa;
    reply[1] = 0x55;
    reply[2] = 7;
    reply[3] = cmd;
    reply[4] = subCmd;
    reply[5] = (unsigned char)ok;
    reply[6] = chksum(reply, 6);
    usb_send(reply, 7);
}

void usb_init()
{
    CmdQueue.front = 0;
    CmdQueue.rear = 0;
}


// 队列轮询，如果有命令就发送
void usb_loop()
{
    if (CmdQueue.front != CmdQueue.rear)
    {
        for (int i = 0; i < sizeof(sendCmd) / sizeof(SendCmd); i++)
        {
            if (sendCmd[i].cmd == CmdQueue.cmdsQueue[CmdQueue.front].cmd
                    && sendCmd[i].subCmd == CmdQueue.cmdsQueue[CmdQueue.front].subCmd)
            {
                if (sendCmd[i].sendDeal)
                {
                    sendCmd[i].sendDeal(sendCmd[i].cmd, sendCmd[i].subCmd, CmdQueue.cmdsQueue[CmdQueue.front].param);
                }
                break;
            }
        }
        CmdQueue.front = (CmdQueue.front + 1) % CMD_QUEUE_NUM;
    }
}

char usb_cmd(unsigned char cmd, unsigned char subCmd, void *param)
{
    if (CmdQueue.front != (CmdQueue.rear + 1) % CMD_QUEUE_NUM)
    {
        CmdQueue.cmdsQueue[CmdQueue.rear].cmd = cmd;
        CmdQueue.cmdsQueue[CmdQueue.rear].subCmd = subCmd;
        CmdQueue.cmdsQueue[CmdQueue.rear].param = param;
        CmdQueue.rear = (CmdQueue.rear + 1) % CMD_QUEUE_NUM;
        return COM_OK;
    }
    return COM_FAIL;
}
uint32_t fac_us = 72000000 / (int)1e6; //(本质：计算1us，SysTick的VAL寄存器减的数目, 1e6=1M ）
/*详细解释：假设系统时钟为72M，那么Systick为系统时钟的八分频——9MHz，也就是每1s，VAL寄存器减去9M
  又因为1us=1/(1M)s，因此每1us，VAL寄存器减去fac_us = 9M/1M = 9
  即fac_us = SystemCoreClock/8/(int)1e6 = SystemCoreClock/(int)8e6;
*/

void delay_us(unsigned long nus)
{
    uint32_t told = SysTick->VAL; /* 刚进入时的计数器值 */
    uint32_t ticks;
    uint32_t tnow, tcnt = 0;
    uint32_t reload = SysTick->LOAD; /* LOAD 的值 */
    ticks = nus * fac_us - 40; /* 需要的节拍数 减去指令补偿*/

    do
    {
        tnow = SysTick->VAL;
        //if (tnow != told)
        {
            tcnt += tnow < told ? told - tnow : reload - tnow + told;
            told = tnow;
        }
    }
    while (tcnt < ticks);
}
